package com.she.iiicoursecenter.manager;

import java.io.InputStream;
import java.lang.ref.SoftReference;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

import com.she.iiicoursecenter.iiiApplication;
import com.she.iiicoursecenter.iface.IResourceBean;
import com.she.iiicoursecenter.iface.IResourceCallback;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Handler;
import android.os.Message;
import android.util.Log;


public class ResourceManager {
	private static ResourceManager mManager;
	private Map<String, SoftReference<Bitmap>> mCache;
	private Context mContext;
	private Executor mExecutor;

	public static final int MAX_THREAD 		= 20;

	private ResourceManager() {
		mCache = new HashMap<String, SoftReference<Bitmap>>();
		mExecutor = Executors.newFixedThreadPool(MAX_THREAD);
	}

	public void init(Context context) {
		mContext = context;
	}

	public static ResourceManager getInstance() {
		if(mManager == null) {
			mManager = new ResourceManager();
		}
		return mManager;
	}

	public void clearCache(String signature) {
		synchronized (mCache) {
			String  key = genKey(signature);
			if(mCache.containsKey(key)) {
				Bitmap bitmap = mCache.remove(key).get();
				if(bitmap != null) {
					//
					if(!bitmap.isRecycled()) bitmap.recycle();
					bitmap = null;
				}
			}
		}
	}

	public void clearAllCache() {
		synchronized (mCache) {
			Set<Entry<String, SoftReference<Bitmap>>> set = mCache.entrySet();
			Object[] objArr = set.toArray();
			for(int i=0; i<objArr.length; i++) {
				@SuppressWarnings("unchecked")
				Entry<String, SoftReference<Bitmap>> entry = (Entry<String, SoftReference<Bitmap>>)objArr[i];
				Bitmap bitmap = entry.getValue().get();
				if(bitmap != null) {
					//
					if(!bitmap.isRecycled()) bitmap.recycle();
					bitmap = null;
				}
			}
			mCache.clear();
			System.gc();
		}
	}

	public void asyncLoad(final IResourceBean bean, final IResourceCallback callback) {
		if(bean != null) {
			final String signature 	= bean.getSignature();
			final String path 		= bean.getPath();
			final int ResId		= bean.getResID();
			// we will not use this feature...
			//final String url = bean.getUrl();

			final int inSampleSize;
			final int scaleWidth;
			final int scaleHeight;

			inSampleSize 	= bean.getInSampleSize();
			scaleWidth 		= bean.getScaleWidth();
			scaleHeight 	= bean.getScaleHeight();

			final String key = genKey(signature);

//			final Handler handler = new Handler(){
//				@Override
//				public void handleMessage(Message msg) {
//					super.handleMessage(msg);
//					if(msg.getData() != null) {
//						if(callback != null) {
//							Log.d("asyncLoad", "bitmap loaded & callback...");
//							callback.onLoaded((Bitmap)msg.obj, bean);
//						}
//					}
//				}
//			};

			// Try to Get Bitmap From Cache. 
			synchronized (mCache) {
				if(key != null && !key.trim().equals("") && mCache.containsKey(key)) {
					Bitmap bitmap = mCache.get(key).get();
					if(bitmap != null && !bitmap.isRecycled() && callback != null) {
						iiiApplication.Log("asyncLoad", "cached bitmap loaded & callback...");
						callback.onLoaded(bitmap, bean);
						return;
					}
				}
			}

			if(callback != null) callback.onLoading(bean);

			mExecutor.execute(new Thread() {
				@Override
				public void run() {
					super.run();
					Bitmap bitmap = null;
					try {
						// Try to get Bitmap from SDCard.
						if(path != null && path.length() > 0) {
							if(inSampleSize > 1) {
								BitmapFactory.Options opts = new BitmapFactory.Options();
								opts.inSampleSize = inSampleSize;
								bitmap = BitmapFactory.decodeFile(path, opts);
							} else {
								bitmap = BitmapFactory.decodeFile(path);
							}
						}
						// Try to get Bitmap from Resource...
						if (ResId != -1){
							BitmapFactory.Options opts = new BitmapFactory.Options();
							opts.inPreferredConfig 	= Bitmap.Config.ARGB_8888;
							opts.inPurgeable 			= true;
							opts.inInputShareable 		= true;
							opts.inJustDecodeBounds 	= true;
							InputStream is = mContext.getResources().openRawResource(ResId);
							BitmapFactory.decodeStream(is, null, opts);
							opts.inJustDecodeBounds 	= false; 
							opts.inSampleSize = inSampleSize;
							bitmap = BitmapFactory.decodeStream(is, null, opts);
						}
						

						if(bitmap != null) {
							if(scaleWidth > 0 && scaleHeight > 0) {
								bitmap = Bitmap.createScaledBitmap(bitmap, scaleWidth, scaleHeight, true);
							}

							if(key != null && !key.trim().equals("")) {
								SoftReference<Bitmap> ref = new SoftReference<Bitmap>(bitmap);
								synchronized (mCache) {
									mCache.put(key, ref);
								}
							}

							//Message message = handler.obtainMessage(0, bitmap);
							//handler.sendMessage(message);
							
							iiiApplication.Log("asyncLoad", "bitmap loaded & callback...");
							callback.onLoaded(bitmap, bean);
							
							return;
						}

						// we will not use this feature...
						//						if(url != null) {
						//							DownloadImageEvent event = DownloadImageEvent.getInstance(bean, mContext);
						//							event.addCallback(new IEventCallback() {
						//								@Override
						//								public void result(Event event, Object result) {
						//									Bitmap bitmap = null;
						//									if(inSampleSize > 1) {
						//										BitmapFactory.Options opts = new BitmapFactory.Options();
						//										opts.inSampleSize = inSampleSize;
						//										bitmap = BitmapFactory.decodeFile(bean.getPath(), opts);
						//									} else {
						//										bitmap = BitmapFactory.decodeFile(bean.getPath());
						//									}
						//									
						//									if(bitmap != null) {
						//										if(scaleWidth > 0 && scaleHeight > 0) {
						//											bitmap = Bitmap.createScaledBitmap(bitmap, scaleWidth, scaleHeight, true);
						//										}
						//										
						//										if(key != null && !key.trim().equals("")) {
						//											SoftReference<Bitmap> ref = new SoftReference<Bitmap>(bitmap);
						//											synchronized (mCache) {
						//												mCache.put(key, ref);
						//											}
						//										}
						//									}
						//									
						//									Message message = handler.obtainMessage(0, bitmap);
						//									handler.sendMessage(message);
						//								}
						//								
						//								@Override
						//								public void progress(Event event, int progress, String tmpPath) {}
						//							});
						//							
						//							EventManager.getInstance().execute(event);
						//						}

					} catch(OutOfMemoryError e) {	
						/*************************
						 * Out of Memory Error! **
						 * **********************/
						e.printStackTrace();

					} catch (Exception e) {
						e.printStackTrace();
					}

				}
			});
		}
	}

	/** Generate the Unique Key of Cache**/
	private String genKey(String signature) {
		if(signature != null && !signature.trim().equals("")) {
			return signature;
		}
		return null;
	}


}
